package routers

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
	"strconv"
	"strings"
	"ztool/common"
	"ztool/models"
)

// streamNoReader zlmediakit无人观看hook接口 /**
func streamNoReader(c *gin.Context) {

	//判定访问的IP是否来自zl
	log.Println("无人观看回调")

	//定义返回结构体
	var noReaderJson models.NoReaderJson

	if err := c.ShouldBind(&noReaderJson); err != nil {
		c.JSON(http.StatusOK, common.RespError(err.Error()))
		return
	}

	go sendCloseStreamRequest(&noReaderJson)

	c.JSON(http.StatusOK, common.RespSuccess("success"))
}

/**
发起关闭流的请求
*/
func sendCloseStreamRequest(noReaderJson *models.NoReaderJson) {
	zlConfig := common.GetZLConfig()

	var urlBuild strings.Builder
	urlBuild.WriteString("http://")
	urlBuild.WriteString(zlConfig.Ip)
	urlBuild.WriteString(":")
	urlBuild.WriteString(strconv.Itoa(zlConfig.Port))
	urlBuild.WriteString("/index/api/close_streams?force=1")

	if "" != noReaderJson.Vhost {
		urlBuild.WriteString("&vhost=")
		urlBuild.WriteString(noReaderJson.Vhost)
	}

	urlBuild.WriteString("&app=")
	urlBuild.WriteString(noReaderJson.App)
	//schema=rtmp&
	urlBuild.WriteString("&stream=")
	urlBuild.WriteString(noReaderJson.Stream)
	//鉴权
	urlBuild.WriteString("&secret=")
	urlBuild.WriteString(zlConfig.Secret)

	url := urlBuild.String()

	resp, err := http.Get(url)
	if err != nil {
		panic(err)
	}

	defer resp.Body.Close()
}

/**
设置zl回调url
*/
func setNoReaderHookUrl() ([]byte, error) {
	var urlBuild strings.Builder
	//http端口
	urlBuild.WriteString("&hook.on_stream_none_reader=")
	urlBuild.WriteString("http://")
	urlBuild.WriteString(common.GetServerConfig().Ip)
	urlBuild.WriteString(":")
	urlBuild.WriteString(strconv.Itoa(common.GetServerConfig().Port))
	urlBuild.WriteString("/zl/stream_none_reader")

	//发送
	urlParams := urlBuild.String()
	return sendSetConfigRequest(urlParams)
}

/**
获取媒体基本信息，常用配置及端口号
*/
func getMediaConfig() (*models.MediaServerConfig, error) {
	zlConfig := common.GetZLConfig()

	var urlBuild strings.Builder
	urlBuild.WriteString("http://")
	urlBuild.WriteString(zlConfig.Ip)
	urlBuild.WriteString(":")
	urlBuild.WriteString(strconv.Itoa(zlConfig.Port))
	urlBuild.WriteString("/index/api/getServerConfig?secret=")
	//鉴权
	urlBuild.WriteString(zlConfig.Secret)
	url := urlBuild.String()

	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		return nil, err
	}

	//返回参数
	var s *models.MediaConfigs
	json.Unmarshal([]byte(body), &s)

	if s.Code != 0 {
		return nil, errors.New("获取参数错误")
	}

	datas := s.Data
	if len(datas) == 0 {
		return nil, errors.New("无法获取服务配置信息")
	}

	return &datas[0], nil
}

/**
发起修改配置参数请求
*/
func sendSetConfigRequest(urlParams string) ([]byte, error) {
	zlConfig := common.GetZLConfig()

	var urlBuild strings.Builder
	urlBuild.WriteString("http://")
	urlBuild.WriteString(zlConfig.Ip)
	urlBuild.WriteString(":")
	urlBuild.WriteString(strconv.Itoa(zlConfig.Port))
	urlBuild.WriteString("/index/api/setServerConfig?secret=")
	//鉴权
	urlBuild.WriteString(zlConfig.Secret)
	urlBuild.WriteString(urlParams)

	url := urlBuild.String()

	log.Printf("发起修改参数请求:%s", url)

	resp, err := http.Get(url)
	if err != nil {
		log.Printf("连接媒体服务器错误，请检查 %s", err.Error())
	}

	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}

/**
	zlmediakitReverseProxy RESTful接口的代理
http://192.168.100.6:9002/zl/api/addStreamProxy?vhost=__default__&app=live&stream=12&url=rtsp://admin:Craftsman_2020@192.168.1.221:554/h264/ch35/main/av_stream&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaXAiOiIiLCJleHAiOjE2NDEzNTE3MzEsImlzcyI6ImNyYWZ0c21hbiJ9.qu0BRQ0Vym4Nz_l58vYII-osB2t7T9o52n0oVdZb35Y
*/
func zlmediakitReverseProxy(c *gin.Context) {

	zlConfig := common.GetZLConfig()
	targetHost := fmt.Sprintf("http://%s:%d", zlConfig.Ip, zlConfig.Port)

	//替换掉前缀
	groupNewURL(c)

	remote, err := url.Parse(targetHost)
	if err != nil {
		log.Fatal("err:%s", err)
		c.Writer.WriteHeader(http.StatusInternalServerError)
		return
	}

	proxy := httputil.NewSingleHostReverseProxy(remote)
	proxy.ServeHTTP(c.Writer, c.Request)
}

/**
组合新流
*/
func groupNewURL(c *gin.Context) {
	//只接收GET请求
	var ognPath string = c.Request.URL.Path
	c.Request.URL.Path = strings.Replace(ognPath, "/zl/", "/index/", 1)
	query := c.Request.URL.Query()

	//额外参数
	//补secrect参数
	adminParam := common.GetZLConfig().Secret

	if len(adminParam) > 0 {
		query.Set("secret", adminParam)
	}

	c.Request.URL, _ = c.Request.URL.Parse(c.Request.URL.Path + "?" + query.Encode())
}

// loadZLRouter 将路由组注册进去
func loadZLRouter(r *gin.Engine) {
	//服务接口
	//无人观看回调
	r.Any("/zl/stream_none_reader", streamNoReader)
}

//loadZLAuthorRoute 代理zl需要认证的部分
func loadZLAuthorRoute(r *gin.Engine) {
	//转发zl RESTful FIXME 建议不要全部代理
	r.Any("/zl/api/*action", zlmediakitReverseProxy)
}
